package com.slfx.function.permission.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.slfx.function.permission.constant.MenuConstants;
import com.slfx.function.permission.dto.MenuQueryDTO;
import com.slfx.function.permission.dto.MenuTreeListDTO;
import com.slfx.function.permission.entity.SystemMenu;
import com.slfx.function.permission.mapper.SystemMenuMapper;
import com.slfx.function.permission.service.ISystemMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.slfx.function.permission.util.BeanCopyUtil;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author slfx
 * @since 2023-01-02
 */
@Service
public class SystemMenuServiceImpl extends ServiceImpl<SystemMenuMapper, SystemMenu> implements ISystemMenuService {

    @Override
    public List<MenuTreeListDTO> queryMenuList(MenuQueryDTO queryParams) {
        QueryWrapper<SystemMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(queryParams.getName()), "name", queryParams.getName());
        queryWrapper.eq("deleted", false);
        queryWrapper.orderByAsc("sort");
        List<SystemMenu> menuList = this.baseMapper.selectList(queryWrapper);
        List<MenuTreeListDTO> list = this.buildMenuTree(menuList);
        return list;
    }

    private List<MenuTreeListDTO> buildMenuTree(List<SystemMenu> menuList) {
        List<MenuTreeListDTO> menuTreeResults = Lists.newArrayList();
        if (CollUtil.isEmpty(menuList)) {
            return menuTreeResults;
        }
        List<MenuTreeListDTO> menuTreeListDTOList = BeanCopyUtil.copyListProperties(menuList, MenuTreeListDTO::new);
        for (Iterator<MenuTreeListDTO> iterator = menuTreeListDTOList.iterator(); iterator.hasNext(); ) {
            MenuTreeListDTO t = iterator.next();
            // 根据传入的某个父节点编码,遍历该父节点的所有子节点
            if (MenuConstants.MENU_ROOT_NODE.equals(t.getParentId())) {
                recursionList(menuTreeListDTOList, t);
                menuTreeResults.add(t);
            }
        }
        if (CollUtil.isEmpty(menuTreeResults)) {
            menuTreeResults = menuTreeListDTOList;
        }

        return menuTreeResults;
    }

    /**
     * 递归列表
     *
     * @param list
     * @param t
     */
    private void recursionList(List<MenuTreeListDTO> list, MenuTreeListDTO t) {
        // 得到子节点列表
        List<MenuTreeListDTO> childList = getChildList(list, t);
        t.setChildren(childList);
        for (MenuTreeListDTO tChild : childList) {
            if (hasChild(list, tChild)) {
                // 判断是否有子节点
                Iterator<MenuTreeListDTO> it = childList.iterator();
                while (it.hasNext()) {
                    MenuTreeListDTO n = it.next();
                    recursionList(list, n);
                }
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<MenuTreeListDTO> getChildList(List<MenuTreeListDTO> list, MenuTreeListDTO t) {
        List<MenuTreeListDTO> childList = Lists.newArrayList();
        Iterator<MenuTreeListDTO> it = list.iterator();
        while (it.hasNext()) {
            MenuTreeListDTO n = it.next();
            if (t.getId().equals(n.getParentId())) {
                childList.add(n);
            }
        }
        return childList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<MenuTreeListDTO> list, MenuTreeListDTO t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    @Override
    public Long saveMenu(SystemMenu sysMenu) {
        this.baseMapper.insert(sysMenu);
        return sysMenu.getId();
    }

    @Override
    public List<MenuTreeListDTO> getUserMenu(String userCode) {
        //查询到用户的角色并且关联的菜单
        List<SystemMenu> systemMenus = this.baseMapper.getUserMenu(userCode);
        List<MenuTreeListDTO> list = this.buildMenuTree(systemMenus);
        return list;
    }
}
